#include "UDP.h"
//构造函数，初始化变量
my_UDP::my_UDP()
{
  rev_packet.v_x = 0;
  rev_packet.v_z = 0;
  rev_status = 0;
}
//UDP初始化函数
void my_UDP::my_UDP_init()
{
  WiFi.mode(WIFI_STA);                          //设置ESP8266为STATION模式
  WiFi.setAutoConnect(false);                   //禁用自动连接
  WiFi.begin(WIFI_ID, WIFI_PASSWORD);           //令ESP8266连接至我们的wifi
  while (WiFi.status() != WL_CONNECTED)         //等待wifi连接完成
  {
    delay(500);
  }
  Serial.printf("Connected to %s\n", WIFI_ID);  //提示wifi连接完成
  Udp.begin(LOCAL_UDP_PORT);                    //以下开启UDP监听并打印输出信息，包括arduino的ip地址和端口号
  Serial.printf("Now listening at IP %s, UDP port %d\n", WiFi.localIP().toString().c_str(), LOCAL_UDP_PORT);
}
//UDP接收函数
bool my_UDP::UDP_rev()
{
  int packetSize = Udp.parsePacket();         //UDP接收数据包并解析，返回数据包的字节数
  if (packetSize)                             //若数据包的字节数大于0，则开始解析
  {
    uint8_t temp_data[8] = {'\0'};            //声明临时数组用于存放数据
    uint8_t temp_data_len = 0;                //声明临时数组索引便于后续操作
    while (packetSize--)                      //根据数据包的字节数循环读取缓冲区的字节，改变状态机的状态
    {
      rev_temp = (uint8_t)Udp.read();         //读取缓冲区的一个字节并存放于rev_temp变量
      if (rev_status == 0)                    //状态机状态为0，此时为检测包头0xff
      {
        if (rev_temp == PACKET_HEAD)          //若检测到包头
        {
          rev_status = 1;                     //改变状态机状态为1
          rev_checksum = 0;                   //将校验和置0
          temp_data_len = 0;                  //将临时数组索引置0
        }
      }
      else if (rev_status == 1)               //状态机状态为1，此时为接收数据部分（共8字节），并存放于temp_data当中备后用
      {
        temp_data[temp_data_len++] = rev_temp;//将数据存入临时数组
        rev_checksum += rev_temp;             //校验和
        if (temp_data_len == 8)               //存够八个字节改变状态为2
        {
          rev_status = 2;
        }
      }
      else if (rev_status == 2)               //状态机状态2，此时计算校验和的低八位
      {
        rev_status = 0;                       //状态机归零
        if ((uint8_t)(rev_checksum % 256) == rev_temp)//对256取模从而得到低八位
        {
          int i, j;
          uint8_t temp[4];
          memset(temp, 0, sizeof(uint8_t) * 4);
          for (i = 1, j = 0; i <= 8; i++, j++)
          {
            temp[j] = temp_data[i - 1];
            if (i % 4 == 0)                   //由于四个字节是一个float类型的数据，因此索引对4取模
            {
              switch ((int)i / 4)
              {
              case 1:
                rev_packet.v_x = *(float *)temp;//(float *)是将temp数组转换为float类型的指针，*(float *)是取指针对应的值
                break;
              case 2:
                rev_packet.v_z = *(float *)temp;
                break;
              }
              j = -1;
              temp_data_len = 0;
            }
          }
          return true;                        //如果校验和正确即解析成功返回true
        }
      }
    }
  }
  return false;
}
